package com.ruoyi.web.controller.system;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SyDataset;
import com.ruoyi.system.domain.SyDatasetInfo;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.utils.MinioFileUtil;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SyCatagory;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 数据目录信息表Controller
 * 
 * @author SYGIS
 * @date 2023-12-22
 */
@RestController
@RequestMapping("/system/catagory")
public class SyCatagoryController extends BaseController {

    @Autowired
    private ISyCatagoryService syCatagoryService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private MinioFileUtil minioFileUtil;

    @Autowired
    private ISyDatasetService datasetService;

    @PostMapping("/getAllPoints")
    public AjaxResult getAllPoints(@RequestBody Map<Object,Object> map){
        // 获取点
        List<Map<Object,Object>> res = new ArrayList<>();
        Map<Object,Object> fRes = new HashMap<>();
        SimpleFeatureCollection simpleFeatureCollection = null;
        ShapefileDataStore shpDataStore = null;
        try {
            String input = minioFileUtil.filePath+map.get("fullname");
            File file = new File(input);
            shpDataStore = new ShapefileDataStore(file.toURL());
            String typeName = shpDataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
            simpleFeatureCollection = featureSource.getFeatures();
            // 输出坐标系
            String toCRS = "EPSG:4609"; // WGS84
            // 输入坐标系
            String fromCRS = "EPSG:26720"; // NAD_1927_CGQ77_UTM_Zone_20N
            CoordinateReferenceSystem fromCRSys = CRS.decode(fromCRS);
            CoordinateReferenceSystem toCRSys = CRS.decode(toCRS);
            MathTransform transform = null;
            if (!fromCRSys.equals(toCRSys)) {
                transform = CRS.findMathTransform(fromCRSys, toCRSys, true);
            }

            if(simpleFeatureCollection.size()>0){
                try (SimpleFeatureIterator iterator1 = simpleFeatureCollection.features()) {
                    while (iterator1.hasNext()) {
                        SimpleFeature feature = iterator1.next();
                        if(feature.getFeatureType().getType("the_geom").getName().toString().equalsIgnoreCase("Point")){
                            fRes.put("type","point");
                            Collection<Property> properties = feature.getProperties();
                            Iterator<Property> propertyIterator = properties.iterator();
                            Geometry geometry = (Geometry) feature.getDefaultGeometry();
                            Geometry newGeometry = JTS.transform(geometry, transform);
                            Map<Object,Object> point = new HashMap<>();
                            point.put("ID",feature.getID().substring(feature.getID().indexOf(".")+1));
                            point.put("UUID",UUID.randomUUID().toString().replaceAll("-", ""));
                            point.put("FULLID",feature.getID());
                            point.put("NAME",feature.getName().toString());
                            point.put("PLANEX",geometry.getCoordinate().x);
                            point.put("PLANEY",geometry.getCoordinate().y);
                            point.put("SPACEX",newGeometry.getCoordinate().x);
                            point.put("SPACEY",newGeometry.getCoordinate().y);
                            res.add(point);
                        }else if(feature.getFeatureType().getType("the_geom").getName().toString().equalsIgnoreCase("MULTILINESTRING")){
                            fRes.put("type","line");
                            Geometry geometry = (Geometry) feature.getDefaultGeometry();
                            Map<Object,Object> linemap = new HashMap<>();
                            if(geometry.getCoordinates().length>0){
                                linemap.put("ID",feature.getID().substring(feature.getID().indexOf(".")+1));
                                linemap.put("FULLID",feature.getID());
                                linemap.put("UUID",UUID.randomUUID().toString().replaceAll("-", ""));
                            }
                            Geometry newGeometry = JTS.transform(geometry, transform);
                            List<Map<Object,Object>> linelist = new ArrayList<>();
                            if(newGeometry.getCoordinates().length>0){
                                for(int i=0;i<newGeometry.getCoordinates().length;i++){
                                    Map<Object,Object> coord = new HashMap<>();
                                    coord.put("X",newGeometry.getCoordinates()[i].x);
                                    coord.put("Y",newGeometry.getCoordinates()[i].y);
                                    linelist.add(coord);
                                }
                            }
                            linemap.put("line",linelist);
                            res.add(linemap);

                        }else if(feature.getFeatureType().getType("the_geom").getName().toString().equalsIgnoreCase("MultiPolygon")){
                            fRes.put("type","polygon");
                            Geometry geometry = (Geometry) feature.getDefaultGeometry();
                            Map<Object,Object> polygonmap = new HashMap<>();
                            if(geometry.getCoordinates().length>0){
                                polygonmap.put("ID",feature.getID().substring(feature.getID().indexOf(".")+1));
                                polygonmap.put("FULLID",feature.getID());
                                polygonmap.put("UUID",UUID.randomUUID().toString().replaceAll("-", ""));
                            }
                            Geometry newGeometry = JTS.transform(geometry, transform);
                            List<Map<Object,Object>> polygonlist = new ArrayList<>();
                            if(newGeometry.getCoordinates().length>0){
                                for(int i=0;i<newGeometry.getCoordinates().length;i++){
                                    Map<Object,Object> coord = new HashMap<>();
                                    coord.put("X",newGeometry.getCoordinates()[i].x);
                                    coord.put("Y",newGeometry.getCoordinates()[i].y);
                                    polygonlist.add(coord);
                                }
                            }
                            polygonmap.put("polygon",polygonlist);
                            res.add(polygonmap);
                        }
                    }
                }
            }
        } catch (Exception exception) {
            logger.info("读取shp失败：" + exception.toString());
        }
        fRes.put("list",res);
        return AjaxResult.success(fRes);
    }

    @PostMapping("/deleteBucketObject")
    public AjaxResult deleteBucketObject(@RequestBody Map<Object,Object> param) throws Exception{
        minioFileUtil.removeObject(param.get("bname").toString(),param.get("oname").toString());
        return AjaxResult.success();
    }

    @GetMapping("/getBucketObjects")
    public AjaxResult getBucketObjects(SyCatagory cata) throws Exception{
        List<Map<Object,Object>> res = minioFileUtil.listBucketObjects(cata.getUuid());
        return AjaxResult.success(res);
    }

    @PostMapping("/getBucketFolderObjects")
    public AjaxResult getBucketFolderObjects(@RequestBody Map<Object,Object> param) throws Exception{
        List<Map<Object,Object>> res = minioFileUtil.listBucketFolderObjects(param.get("uuid").toString(),param.get("folder").toString());
        return AjaxResult.success(res);
    }

    @GetMapping("/getTreeRootData")
    public AjaxResult getTreeRootData() {
        SyDataset dataset = new SyDataset();
        dataset.setStatus(1);
        List<SyDataset> list = datasetService.selectSyDatasetList(dataset);
        List<Map<Object,Object>> res = new ArrayList<>();
        if(list.size()>0){
            for(SyDataset syDataset:list){
                Map<Object,Object> datasetMap = new HashMap<>();
                datasetMap.put("name",syDataset.getName());
                datasetMap.put("uuid",syDataset.getUuid());
                List<Map<Object,Object>> firstSub = new ArrayList<>();
                SyCatagory fCata = new SyCatagory();
                fCata.setStatus(1);
                fCata.setParentId("0");
                fCata.setDatasetIds(syDataset.getUuid());
                List<SyCatagory> firstCatas = syCatagoryService.selectSyCatagoryList(fCata);
                if(firstCatas.size()>0){
                    for(SyCatagory fcata:firstCatas){
                        Map<Object,Object> firstMap = new HashMap<>();
                        firstMap.put("name",fcata.getName());
                        firstMap.put("uuid",fcata.getUuid());
                        SyCatagory subcata = new SyCatagory();
                        subcata.setParentId(fCata.getParentId());
                        subcata.setStatus(1);
                        List<SyCatagory> subCataList = syCatagoryService.selectSyCatagoryList(subcata);
                        if(subCataList.size()>0){
                            List<Map<Object,Object>> subLeaf = getAllSub1(fcata.getUuid());
                            firstMap.put("children",subLeaf);
                            firstMap.put("dataType",fcata.getDataType());
                            firstMap.put("code",fcata.getCode());
                            firstMap.put("level","parent");
                        }else{
                            firstMap.put("children",null);
                            firstMap.put("dataType",fcata.getDataType());
                            firstMap.put("code",fcata.getCode());
                            firstMap.put("level","sub");
                        }
                        firstSub.add(firstMap);
                    }
                }
                datasetMap.put("children",firstSub);
                datasetMap.put("level","root");
                res.add(datasetMap);
            }
        }
        logger.info("---------res---------"+res);
        return AjaxResult.success(res);
    }

    public List<Map<Object,Object>> getAllSub1(String parentId){
        List<Map<Object,Object>> res = new ArrayList<>();
        SyCatagory subcata = new SyCatagory();
        subcata.setParentId(parentId);
        subcata.setStatus(1);
        List<SyCatagory> subCataList = syCatagoryService.selectSyCatagoryList(subcata);
        if(subCataList.size()>0) {
            for (SyCatagory cata : subCataList) {
                Map<Object,Object> subtMap = new HashMap<>();
                subtMap.put("name",cata.getName());
                subtMap.put("uuid",cata.getUuid());
                SyCatagory leafcata = new SyCatagory();
                leafcata.setParentId(cata.getUuid());
                leafcata.setStatus(1);
                List<SyCatagory> subLeafCata = syCatagoryService.selectSyCatagoryList(leafcata);
                if(subLeafCata.size()>0){
                    List<Map<Object,Object>> subList = new ArrayList<>();
                    for(SyCatagory subcatainfo:subLeafCata){
                        List<Map<Object,Object>> leafinfos = getAllSub1(subcatainfo.getUuid());
                        Map<Object,Object> subMap = new HashMap<>();
                        subMap.put("children",leafinfos);
                        subMap.put("dataType",subcatainfo.getDataType());
                        subMap.put("name",subcatainfo.getName());
                        subMap.put("uuid",subcatainfo.getUuid());
                        subMap.put("code",subcatainfo.getCode());
                        if(leafinfos.size()>0){
                            subMap.put("level","parent");
                        }else{
                            subMap.put("level","sub");
                        }
                        subList.add(subMap);
                    }
                    subtMap.put("children",subList);
                    subtMap.put("level","parent");
                }else{
                    subtMap.put("children",null);
                    subtMap.put("level","sub");
                }
                subtMap.put("dataType",cata.getDataType());
                subtMap.put("code",cata.getCode());
                res.add(subtMap);
            }
        }
        return res;
    }

    public List<Map<Object,Object>> getAllSub(String parentId){
        List<Map<Object,Object>> res = new ArrayList<>();
        SyCatagory subcata = new SyCatagory();
        subcata.setParentId(parentId);
        subcata.setStatus(1);
        List<SyCatagory> subCataList = syCatagoryService.selectSyCatagoryList(subcata);
        if(subCataList.size()>0){
            for(SyCatagory cata:subCataList){
                Map<Object,Object> subtMap = new HashMap<>();
                subtMap.put("name",cata.getName());
                subtMap.put("uuid",cata.getUuid());
                SyCatagory leafcata = new SyCatagory();
                leafcata.setParentId(cata.getUuid());
                leafcata.setStatus(1);
                List<SyCatagory> subLeafCata = syCatagoryService.selectSyCatagoryList(subcata);
                if(subLeafCata.size()>0){
                    for (SyCatagory leaf:subLeafCata){
                        List<Map<Object,Object>> leafinfos = getAllSub(leaf.getUuid());
                        subtMap.put("children",leafinfos);
                    }
                    subtMap.put("dataType",cata.getDataType());
                    subtMap.put("code",cata.getCode());
                    subtMap.put("level","parent");
                }else{
                    subtMap.put("children",null);
                    subtMap.put("dataType",cata.getDataType());
                    subtMap.put("code",cata.getCode());
                    subtMap.put("level","sub");
                }
                res.add(subtMap);
            }
        }
        return res;
    }

    @PostMapping("/saveDatasetCatagory")
    public AjaxResult saveDatasetCatagory(@RequestBody SyCatagory cata) {
        SyCatagory cataInfo = new SyCatagory();
        cataInfo.setStatus(1);
        cataInfo.setParentId("0");
        List<SyCatagory> catagories = syCatagoryService.selectSyCatagoryList(cataInfo);
        if(catagories.size()>0) {
            for (SyCatagory info : catagories) {
                String datasetIds = info.getDatasetIds();
                if(info.getDatasetIds()!=null){
                    if(datasetIds.indexOf(","+cata.getDatasetId())>=0){
                        datasetIds = datasetIds.replaceAll(","+cata.getDatasetId(),"");
                    }
                    if(datasetIds.indexOf(cata.getDatasetId())>=0){
                        datasetIds = datasetIds.replaceAll(cata.getDatasetId(),"");
                    }
                }
                info.setDatasetIds(datasetIds);
                syCatagoryService.updateSyCatagory(info);
            }
        }
        String[] ids = cata.getDatasetIds().split(",");
        if(ids.length>0){
            for(String id:ids){
                SyCatagory catagory = syCatagoryService.selectSyCatagoryByUuid(id);
                if(catagory!=null){
                    catagory.setDatasetIds(catagory.getDatasetIds()+","+cata.getDatasetId());
                }
                syCatagoryService.updateSyCatagory(catagory);
            }
        }
        return AjaxResult.success();
    }

    @GetMapping("/listCatagoryDataEffect")
    public AjaxResult listCatagoryDataEffect(SyCatagory cata) {
        cata.setStatus(1);
        cata.setParentId("0");
        List<SyCatagory> catagories = syCatagoryService.selectSyCatagoryList(cata);
        if(catagories.size()>0){
            for (SyCatagory info:catagories){
                SysUser user = userService.selectUserById(Long.parseLong(info.getCreateBy()));
                if(user!=null){
                    info.setCreator(user.getNickName());
                }
                if(info.getDatasetIds()!=null){
                    if(info.getDatasetIds().indexOf(cata.getDatasetId())>=0||info.getDatasetIds().indexOf(","+cata.getDatasetId())>=0){
                        info.setSelected(true);
                    }else{
                        info.setSelected(false);
                    }
                }else{
                    info.setSelected(false);
                }
            }
        }
        return AjaxResult.success(catagories);
    }

    @GetMapping("/listCatagoryData")
    public AjaxResult listCatagoryData(SyCatagory cata) {
        List<SyCatagory> catagories = syCatagoryService.selectSyCatagoryList(cata);
        if(catagories.size()>0){
            for (SyCatagory info:catagories){
                SysUser user = userService.selectUserById(Long.parseLong(info.getCreateBy()));
                if(user!=null){
                    info.setCreator(user.getNickName());
                }
            }
        }
        return AjaxResult.success(catagories);
    }

    @GetMapping("/getOrdernum")
    public AjaxResult getOrdernum(SyCatagory cata) {
        Map<Object,Object> res = new HashMap<>();
        List<SyCatagory> catagories = syCatagoryService.selectSyCatagoryList(cata);
        if(catagories.size()>0){
            res.put("orderNum",catagories.get(catagories.size()-1).getOrderNum()+1);
        }else{
            res.put("orderNum",1);
        }
        return AjaxResult.success(res);
    }

    @GetMapping("/getCataCode")
    public AjaxResult getCataCode(SyCatagory cata) {
        Map<Object,Object> res = new HashMap<>();
        String code = getFirstSpell(cata.getName());
        SyCatagory catagory = new SyCatagory();
        catagory.setCode(code);
        catagory.setParentId(cata.getParentId());
        List<SyCatagory> catagories = syCatagoryService.selectSyCatagoryList(catagory);
        if(catagories.size()>0){
            return AjaxResult.error("目录名称重复,请重新输入！");
        }else{
            res.put("code",code);
            return AjaxResult.success(res);
        }
    }

    public static String getFirstSpell(String chinese) {
        StringBuffer pybf = new StringBuffer();
        char[] arr = chinese.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > 128) {
                try {
                    String[] temp = PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat);
                    if (temp != null) {
                        pybf.append(temp[0].charAt(0));
                    }
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                pybf.append(arr[i]);
            }
        }
        return pybf.toString().replaceAll("\\W", "").trim().toUpperCase();
    }

    /**
     * 查询数据目录信息表列表
     */
    @GetMapping("/list")
    public TableDataInfo list(SyCatagory syCatagory) {
        startPage();
        List<SyCatagory> list = syCatagoryService.selectSyCatagoryList(syCatagory);
        return getDataTable(list);
    }

    /**
     * 导出数据目录信息表列表
     */
    @Log(title = "数据目录信息表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SyCatagory syCatagory) {
        List<SyCatagory> list = syCatagoryService.selectSyCatagoryList(syCatagory);
        ExcelUtil<SyCatagory> util = new ExcelUtil<SyCatagory>(SyCatagory.class);
        util.exportExcel(response, list, "数据目录信息表数据");
    }

    /**
     * 获取数据目录信息表详细信息
     */
    @GetMapping(value = "/{uuid}")
    public AjaxResult getInfo(@PathVariable("uuid") String uuid) {
        return success(syCatagoryService.selectSyCatagoryByUuid(uuid));
    }

    /**
     * 新增数据目录信息表
     */
    @Log(title = "数据目录信息表", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SyCatagory syCatagory) {
        syCatagory.setUuid(UUID.randomUUID().toString().replaceAll("-", ""));
        syCatagory.setCreateBy(SecurityUtils.getLoginUser().getUserId().toString());
        syCatagory.setCreateTime(new Date());
        SysDept dept = deptService.selectDeptById(SecurityUtils.getLoginUser().getUser().getDeptId());
        if(dept!=null){
            syCatagory.setDeptId(SecurityUtils.getLoginUser().getUser().getDeptId());
            syCatagory.setDeptName(dept.getDeptName());
        }
        syCatagory.setDatasetIds(syCatagory.getDatasetId());
        syCatagoryService.insertSyCatagory(syCatagory);
        return AjaxResult.success(syCatagory);
    }

    @PostMapping("/createBucket")
    public AjaxResult createBucket(@RequestBody SyCatagory syCatagory) throws Exception {
        // 创建minio 存储筒
        if(!minioFileUtil.checkBucketExist(syCatagory.getUuid().toLowerCase())){
            minioFileUtil.createBucket(syCatagory.getUuid().toLowerCase());
            if(minioFileUtil.checkBucketExist(syCatagory.getUuid().toLowerCase())){
                Date now = new Date();
                SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
                minioFileUtil.startBucketPolicy(syCatagory.getUuid().toLowerCase(),format.format(now));
            }
        }
        return AjaxResult.success();
    }

    /**
     * 修改数据目录信息表
     */
    @Log(title = "数据目录信息表", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SyCatagory syCatagory) {
        return toAjax(syCatagoryService.updateSyCatagory(syCatagory));
    }

    /**
     * 删除数据目录信息表
     */
    @Log(title = "数据目录信息表", businessType = BusinessType.DELETE)
	@DeleteMapping("/{uuids}")
    public AjaxResult remove(@PathVariable String[] uuids) {
        SyCatagory catagory = new SyCatagory();
        catagory.setParentId(uuids[0]);
        List<SyCatagory> catas = syCatagoryService.selectSyCatagoryList(catagory);
        if(catas.size()>0){
            try {
                deleteSubCatas(catas);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        try {
            minioFileUtil.clearBucket(uuids[0].toLowerCase());
            minioFileUtil.deleteBucket(uuids[0].toLowerCase());
        }catch (Exception e){
            e.printStackTrace();
        }
        return toAjax(syCatagoryService.deleteSyCatagoryByUuids(uuids));
    }

    public void deleteSubCatas(List<SyCatagory> res) throws Exception{
        if(res.size()>0){
            for(SyCatagory catagory:res){
                SyCatagory cata = new SyCatagory();
                cata.setParentId(catagory.getUuid());
                List<SyCatagory> subs = syCatagoryService.selectSyCatagoryList(cata);
                if(subs.size()>0){
                    for (SyCatagory minisub:subs){
                        syCatagoryService.deleteSyCatagoryByUuid(minisub.getUuid());
                    }
                }
                syCatagoryService.deleteSyCatagoryByUuid(catagory.getUuid());
                minioFileUtil.clearBucket(catagory.getUuid().toLowerCase());
                minioFileUtil.deleteBucket(catagory.getUuid().toLowerCase());
                deleteSubCatas(subs);
            }
        }
    }

    @PostMapping("/deleteBucket")
    public AjaxResult deleteBucket(@RequestBody SyCatagory syCatagory) throws Exception {
        if(minioFileUtil.checkBucketExist(syCatagory.getUuid().toLowerCase())){
            minioFileUtil.clearBucket(syCatagory.getUuid().toLowerCase());
            minioFileUtil.deleteBucket(syCatagory.getUuid().toLowerCase());
        }
        return AjaxResult.success();
    }
}
